
package fileby.ctrl.actions.impl;


import com.google.inject.Inject;
import com.google.inject.Singleton;

import fileby.util.IObservable;
import fileby.core.UpdateEvent;
import fileby.core.ActionKey;
import fileby.ctrl.actions.IActionProvider;
import fileby.model.IClipboardManager;
import fileby.model.IFavoriteManager;
import fileby.model.IFileManager;
import fileby.model.IMagicBoxManager;
import fileby.model.IModel;
import fileby.model.ISelectionManager;
import fileby.model.ISourceHandler;
import fileby.model.impl.sources.IFileSource;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashMap;
import java.util.Map;
import javax.swing.Action;

/**
 *
 * @author Jacob
 */
@Singleton
public final class ActionController implements IActionProvider, PropertyChangeListener {

    private final Map<ActionKey, Action> dependingActions = new HashMap<ActionKey, Action>();
    private final Map<ActionKey, Action> alwaysEnabledActions = new HashMap<ActionKey, Action>();

    private boolean canAdd;
    private IClipboardManager clipboardManager;
    private IFavoriteManager favoriteManager;
    private IFileManager fileManager;
    private IMagicBoxManager magicBoxManager;
    private ISelectionManager selectionManager;
    private ISourceHandler sourceHandler;
    private IModel model;

    @Inject
    private ActionController(IObservable observable, IClipboardManager clipboardManager,
            IFavoriteManager favoriteManager, IFileManager fileManager,
            IMagicBoxManager magicBoxManager, ISelectionManager selectionManager,
            ISourceHandler sourceHandler, IModel model) {

        observable.addPropertyChangeListener(this);

        this.clipboardManager = clipboardManager;
        this.favoriteManager = favoriteManager;
        this.fileManager = fileManager;
        this.magicBoxManager = magicBoxManager;
        this.selectionManager = selectionManager;
        this.sourceHandler = sourceHandler;
        this.model = model;
        initActions();
    }

    public Action getControl(ActionKey ctrl) {
        if( ctrl == null ) {
            throw new IllegalArgumentException("Control null");
        }
        switch (ctrl) {
            case REMOVE_FROM_MAGIC_BOX:
                return new RemoveFromMagicBoxAction(magicBoxManager);
            case RENAME:
                return new RenameAction(fileManager, selectionManager);
            case REMOVE_FROM_FAVORITES:
                return new RemoveFromFavoritesAction(favoriteManager);
            default:
                if(alwaysEnabledActions.containsKey(ctrl))
                    return alwaysEnabledActions.get(ctrl);
                else
                    return dependingActions.get(ctrl);
        }
    }

    public void propertyChange(PropertyChangeEvent evt) {

        if (UpdateEvent.valueOf(evt.getPropertyName()) == UpdateEvent.CURRENT_SOURCE_CHANGE) {
            canAdd = ((IFileSource)evt.getNewValue()).canAdd();
            dependingActions.get(ActionKey.CREATE_FOLDER).setEnabled(canAdd);
            dependingActions.get(ActionKey.PASTE).setEnabled(canAdd);
        }
        else if (UpdateEvent.valueOf(evt.getPropertyName()) == UpdateEvent.CONTENT_CHANGE) {
            int files = selectionManager.getSelectedFiles().size();
            if (files == 0) {
                for (ActionKey c : dependingActions.keySet())
                        dependingActions.get(c).setEnabled(false);
            } else {
                for (Action a: dependingActions.values())
                    a.setEnabled(true);
                if (files == 1)
                    dependingActions.get(ActionKey.OPEN_IN_NEW_TAB).setEnabled(!selectionManager.getSelectedFiles().get(0).isFile());
                else
                    dependingActions.get(ActionKey.OPEN_IN_NEW_TAB).setEnabled(false);
            }
            dependingActions.get(ActionKey.CREATE_FOLDER).setEnabled(canAdd);
            dependingActions.get(ActionKey.PASTE).setEnabled(canAdd);
        }
    }

    private void initActions(){
        // Actions which depend on some state
        dependingActions.put(ActionKey.CREATE_FOLDER, new CreateFolderAction(fileManager));

        dependingActions.put(ActionKey.COPY, new CopyAction(clipboardManager));
        dependingActions.put(ActionKey.PASTE, new PasteAction(clipboardManager));
        dependingActions.put(ActionKey.CUT, new CutAction(clipboardManager));

        dependingActions.put(ActionKey.DELETE, new DeleteAction(fileManager));
        dependingActions.put(ActionKey.RENAME, new RenameAction(fileManager, selectionManager));

        dependingActions.put(ActionKey.OPEN, new OpenAction(fileManager));
        dependingActions.put(ActionKey.OPEN_IN_NEW_TAB, new OpenInNewTabAction(fileManager));

        dependingActions.put(ActionKey.ADD_TO_FAVORITES, new AddToFavoritesAction(favoriteManager,selectionManager));
 
        dependingActions.put(ActionKey.EXPORT_MAGIC_BOX,new ExportMagicBoxAction(magicBoxManager));
        dependingActions.put(ActionKey.IMPORT_MAGIC_BOX,new ImportMagicBoxAction(magicBoxManager));




        // Actions which are always enabled
        alwaysEnabledActions.put(ActionKey.SELECT_ALL, new SelectAllAction(selectionManager));

        alwaysEnabledActions.put(ActionKey.NEW_TAB, new NewTabAction(sourceHandler));
        alwaysEnabledActions.put(ActionKey.CLOSE_TAB, new CloseTabAction(sourceHandler));
        alwaysEnabledActions.put(ActionKey.CLOSE_ACTIVE_TAB, new CloseActiveTabAction(sourceHandler));
        alwaysEnabledActions.put(ActionKey.QUIT, new QuitAction(model));

        alwaysEnabledActions.put(ActionKey.SHOW_ABOUT_BOX, new ShowAboutBoxAction());
        alwaysEnabledActions.put(ActionKey.CLOSE_ABOUT_BOX, new CloseAboutBoxAction());

        alwaysEnabledActions.put(ActionKey.SEARCH, new SearchAction(fileManager));
        alwaysEnabledActions.put(ActionKey.REMOVE_FROM_FAVORITES, new RemoveFromFavoritesAction(favoriteManager));

        alwaysEnabledActions.put(ActionKey.REMOVE_FROM_MAGIC_BOX, new RemoveFromMagicBoxAction(magicBoxManager));
        alwaysEnabledActions.put(ActionKey.EXECUTE_MAGIC_BOX,new ExecuteMagicBoxAction(magicBoxManager));
        alwaysEnabledActions.put(ActionKey.CLEAR_MAGIC_BOX, new ClearMagicBoxAction(magicBoxManager));
        alwaysEnabledActions.put(ActionKey.LOAD_PLUGIN, new LoadPluginAction(magicBoxManager));
    }
}
